﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.ObjectSweptVolume.CApObjectSweptVolumeCreator
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using EngineeringInternalExtension;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Tecnomatix.Engineering;
using Tecnomatix.Engineering.PrivateImplementationDetails;
using Tecnomatix.Planning;


namespace DnProcessSimulateCommands.ObjectSweptVolume;

public class CApObjectSweptVolumeCreator
{
  private const double SWEPT_VOLUME_TRANSPARENCY_LEVEL = 0.7;
  private IEnumerable<CApObjectSweptVolumeSamplesCollector> m_samplesCollectors;
  private double m_accuracy;
  private double m_clearance;
  private TxSweptVolume_MayProceedCalculation m_mayProceedCallBack;
  private bool m_shouldCreateMultipleContainers = true;
  private bool m_autoInflateSweptVolumes;
  private TxColor m_svColor;
  private List<KeyValuePair<ITxObject, TxSweptVolumeCalculationData>> m_objToCalculationDataPairs = new List<KeyValuePair<ITxObject, TxSweptVolumeCalculationData>>();
  private Dictionary<string, List<ITxPartAppearance>> m_partExtIdToExistingAppearances = new Dictionary<string, List<ITxPartAppearance>>();
  private bool m_partExtIdToExistingAppearances_IsInitialized;
  private Dictionary<string, ITxPartAppearance> m_partExtIdToTempAppearance = new Dictionary<string, ITxPartAppearance>();
  private Dictionary<ITxComponent, List<ITxSkidAppearance>> m_skidToExistingAppearances = new Dictionary<ITxComponent, List<ITxSkidAppearance>>();
  private bool m_skidToExistingAppearances_IsInitialized;
  private Dictionary<ITxComponent, ITxSkidAppearance> m_skidToTempAppearance = new Dictionary<ITxComponent, ITxSkidAppearance>();
  private TxSweptVolumeContainer m_sweptVolumeContainer;
  private string m_entityName;
  private bool m_shouldAbort;
  private TxObjectList<ITxDisplayableObject> m_blankedObjsBeforeCalculate = new TxObjectList<ITxDisplayableObject>(0);

  public CApObjectSweptVolumeCreator(
    IEnumerable<CApObjectSweptVolumeSamplesCollector> samplesCollectors,
    double accuracy,
    double clearance,
    bool shouldCreateMultipleContainers,
    TxSweptVolume_MayProceedCalculation mayProceedCallBack)
  {
    this.m_samplesCollectors = samplesCollectors;
    this.m_accuracy = accuracy;
    this.m_clearance = clearance;
    this.m_shouldCreateMultipleContainers = shouldCreateMultipleContainers;
    this.m_mayProceedCallBack = mayProceedCallBack;
    this.m_autoInflateSweptVolumes = TxApplication.Options.Motion.AutoInflateSweptVolumes;
    this.m_svColor = TxColor.FromBgrColor(TxApplication.Options.Color.SolidColor);
    this.m_svColor.Transparency = 0.7;
  }

  public bool ShouldAbort
  {
    get => this.m_shouldAbort;
    set => this.m_shouldAbort = value;
  }

  public event EventHandler BeforeCalculatingSweptVolumeEntity;

  private void OnBeforeCalculatingSweptVolumeEntity()
  {
    if (this.BeforeCalculatingSweptVolumeEntity == null)
      return;
    this.BeforeCalculatingSweptVolumeEntity((object) this, new EventArgs());
  }

  public void Execute()
  {
    TxApplication.ActiveUndoManager.ClearAllTransactions();
    this.beforeExecute();
    try
    {
      this.execute();
    }
    catch (Exception ex)
    {
    }
    finally
    {
      this.afterExecute();
      TxApplication.ActiveUndoManager.ClearAllTransactions();
      TxApplication.RefreshDisplay();
    }
  }

  private void beforeExecute()
  {
    foreach (CApObjectSweptVolumeSamplesCollector samplesCollector in this.m_samplesCollectors)
    {
      if (samplesCollector.RootObject.IsValid())
      {
        KeyValuePair<ITxObject, TxSweptVolumeCalculationData> keyValuePair = new KeyValuePair<ITxObject, TxSweptVolumeCalculationData>(samplesCollector.RootObject, new TxSweptVolumeCalculationData());
        TxSweptVolumeCalculationData volumeCalculationData1 = keyValuePair.Value;
        volumeCalculationData1.AutoInflateSweptVolume = this.m_autoInflateSweptVolumes;
        Dictionary<string, CApObjectSweptVolumeSample>.Enumerator enumerator = samplesCollector.ObjIdToSampleMap.GetEnumerator();
        while (enumerator.MoveNext())
        {
          CApObjectSweptVolumeSample sweptVolumeSample = enumerator.Current.Value;
          if (sweptVolumeSample is CApObjectSweptVolumeCableSample)
          {
            CApObjectSweptVolumeCableSample volumeCableSample = sweptVolumeSample as CApObjectSweptVolumeCableSample;
            TxCableSweptVolumeCalculationData volumeCalculationData2 = new TxCableSweptVolumeCalculationData(volumeCableSample.Radius);
            foreach (List<TxVector> controlPointsList in volumeCableSample.ControlPointsLists)
              volumeCalculationData2.AppendControlPoints(controlPointsList);
            volumeCalculationData1.AddCableData(volumeCalculationData2);
          }
          else if (sweptVolumeSample is CApObjectSweptVolumeLocatableSample)
          {
            CApObjectSweptVolumeLocatableSample sample = sweptVolumeSample as CApObjectSweptVolumeLocatableSample;
            ITxLocatableObject replacementObject = sample.Object as ITxLocatableObject;
            if (!((ITxObject) replacementObject).IsValid())
              replacementObject = this.GetOrCreateReplacementObject((CApObjectSweptVolumeSample) sample);
            if (replacementObject != null)
            {
              List<TxTransformation> locations = (sweptVolumeSample as CApObjectSweptVolumeLocatableSample).Locations;
              volumeCalculationData1.AddObjectData(new TxObjectSweptVolumeCalculationData(replacementObject, locations.ToArray()));
            }
          }
        }
        this.m_objToCalculationDataPairs.Add(keyValuePair);
      }
    }
  }

  private void afterExecute()
  {
    foreach (ITxObject itxObject in this.m_partExtIdToTempAppearance.Values)
      this.SafeDeleteObject(itxObject);
    this.m_partExtIdToTempAppearance.Clear();
    foreach (ITxObject itxObject in this.m_skidToTempAppearance.Values)
      this.SafeDeleteObject(itxObject);
    this.m_skidToTempAppearance.Clear();
  }

  private void execute()
  {
    if (this.m_shouldCreateMultipleContainers)
      this.execute_MultipleContainers();
    else
      this.execute_SingleContainer();
  }

  private void execute_MultipleContainers()
  {
    foreach (KeyValuePair<ITxObject, TxSweptVolumeCalculationData> calculationDataPair in this.m_objToCalculationDataPairs)
    {
      if (this.ShouldAbort)
        break;
      this.m_sweptVolumeContainer = this.CreateSweptVolumeContainer(this.GenerateSweptVolumeContainerName(calculationDataPair.Key.Name, this.m_accuracy, this.m_clearance));
      try
      {
        this.GenerateSweptVolumeEntity(this.m_sweptVolumeContainer, calculationDataPair.Value, StringTable.OSV_SWEPT_VOLUME_ENTITY_NAME);
      }
      catch (Exception ex)
      {
        if (this.m_sweptVolumeContainer != null)
        {
          this.SafeDeleteObject((ITxObject) this.m_sweptVolumeContainer);
          this.m_sweptVolumeContainer = (TxSweptVolumeContainer) null;
        }
      }
      if (this.m_sweptVolumeContainer != null && this.ShouldAbort)
      {
        this.SafeDeleteObject((ITxObject) this.m_sweptVolumeContainer);
        this.m_sweptVolumeContainer = (TxSweptVolumeContainer) null;
      }
      if (this.m_sweptVolumeContainer != null)
        this.SetSVColor((ITxDisplayableObject) this.m_sweptVolumeContainer);
    }
  }

  private void execute_SingleContainer()
  {
    this.m_sweptVolumeContainer = this.CreateSweptVolumeContainer(this.GenerateSweptVolumeContainerName(StringTable.OSV_SWEPT_VOLUME_COMPONENT_NAME_UNITED, this.m_accuracy, this.m_clearance));
    foreach (KeyValuePair<ITxObject, TxSweptVolumeCalculationData> calculationDataPair in this.m_objToCalculationDataPairs)
    {
      if (!this.ShouldAbort)
      {
        ITxObject key = calculationDataPair.Key;
        try
        {
          this.GenerateSweptVolumeEntity(this.m_sweptVolumeContainer, calculationDataPair.Value, key.Name);
        }
        catch (Exception ex)
        {
        }
      }
      else
        break;
    }
    if (this.m_sweptVolumeContainer != null && this.ShouldAbort)
    {
      this.SafeDeleteObject((ITxObject) this.m_sweptVolumeContainer);
      this.m_sweptVolumeContainer = (TxSweptVolumeContainer) null;
    }
    if (this.m_sweptVolumeContainer == null)
      return;
    this.SetSVColor((ITxDisplayableObject) this.m_sweptVolumeContainer);
  }

  private string GenerateSweptVolumeContainerName(string prefix, double accuracy, double clearance)
  {
    string str1 = prefix;
    string linearUnitName = TxApplication.Options.Units.LinearUnitName;
    double linearMultiplier = TxApplication.Options.Units.LinearMultiplier;
    string str2 = "{0:f";
    string format = linearMultiplier != 1.0 ? $"{str2}{TxApplication.Options.Units.LinearDigitsAfterDecimalPoint.ToString()}}}" : str2 + "0}";
    double num1 = accuracy / linearMultiplier;
    string str3 = $"{str1}_{string.Format(format, (object) num1)}{linearUnitName}";
    if (clearance > 0.0)
    {
      double num2 = clearance / linearMultiplier;
      str3 = $"{$"{str3}_{StringTable.OSV_SWEPT_VOLUME_COMPONENT_NAME_CLEARANCE}"}_{string.Format(format, (object) num2)}{linearUnitName}";
    }
    return TxApplication.ActiveDocument.PhysicalRoot.GetUniqueDisplayName($"{str3}_{StringTable.OSV_SWEPT_VOLUME_COMPONENT_NAME_VOLUME}");
  }

  private TxSweptVolumeContainer CreateSweptVolumeContainer(string name)
  {
    TxSweptVolumeContainerCreationData containerCreationData1 = new TxSweptVolumeContainerCreationData();
    ((TxObjectCreationData) containerCreationData1).Name = name;
    containerCreationData1.Accuracy = this.m_accuracy;
    containerCreationData1.Clearance = this.m_clearance;
    using (TxSweptVolumeContainerCreationData containerCreationData2 = containerCreationData1)
      return TxApplication.ActiveDocument.PhysicalRoot.CreateSweptVolumeContainer(containerCreationData2) as TxSweptVolumeContainer;
  }

  private ITxLocatableObject GenerateSweptVolumeEntity(
    TxSweptVolumeContainer svContainer,
    TxSweptVolumeCalculationData calculationData,
    string entityName)
  {
    ITxLocatableObject sweptVolumeEntity = (ITxLocatableObject) null;
    this.m_entityName = entityName;
    this.beforeCalculateSweptVolume(calculationData);
    try
    {
      ITxLocatableObject lastDirectEntity = this.GetLastDirectEntity((ITxObjectCollection) svContainer);
      this.OnBeforeCalculatingSweptVolumeEntity();
      svContainer.CalculateSweptVolume(calculationData, this.m_mayProceedCallBack);
      if (!this.ShouldAbort)
      {
        sweptVolumeEntity = this.GetLastDirectEntity((ITxObjectCollection) svContainer);
        if (sweptVolumeEntity != null)
        {
          if (sweptVolumeEntity != lastDirectEntity)
          {
            ((ITxObject) sweptVolumeEntity).Name = this.m_entityName;
            this.SetSVColor(sweptVolumeEntity as ITxDisplayableObject);
          }
          else
            sweptVolumeEntity = (ITxLocatableObject) null;
        }
      }
    }
    catch (TxSweptVolumeCalculationFailedException ex)
    {
      this.afterCalculateSweptVolume();
      throw ex;
    }
    this.afterCalculateSweptVolume();
    return sweptVolumeEntity;
  }

  private void SetSVColor(ITxDisplayableObject obj)
  {
    try
    {
      obj.Color = this.m_svColor;
    }
    catch
    {
    }
  }

  private ITxLocatableObject GetLastDirectEntity(ITxObjectCollection coll)
  {
    TxObjectList directDescendants = coll.GetDirectDescendants((ITxTypeFilter) new TxTypeFilter(typeof (ITxLocatableObject)));
    return ((Collection<ITxObject>) directDescendants).Count > 0 ? ((Collection<ITxObject>) directDescendants)[((Collection<ITxObject>) directDescendants).Count - 1] as ITxLocatableObject : (ITxLocatableObject) null;
  }

  private ITxLocatableObject GetOrCreateReplacementObject(CApObjectSweptVolumeSample sample)
  {
    switch (sample)
    {
      case CApObjectSweptVolumePartAppearanceSample _:
        return this.GetOrCreatePartAppearance(sample as CApObjectSweptVolumePartAppearanceSample);
      case CApObjectSweptVolumeSkidAppearanceSample _:
        return this.GetOrCreateSkidAppearance(sample as CApObjectSweptVolumeSkidAppearanceSample);
      case CApObjectSweptVolumeSkidAppearanceChildSample _:
        return this.GetOrCreateSkidAppearanceChild(sample as CApObjectSweptVolumeSkidAppearanceChildSample);
      default:
        return (ITxLocatableObject) null;
    }
  }

  private void InitExistingPartAppearances()
  {
    if (this.m_partExtIdToExistingAppearances_IsInitialized)
      return;
    foreach (ITxPartAppearance physicalPartAppearance in (Collection<ITxObject>) new TxBIWLineServices().GetAllPhysicalPartAppearances(true))
    {
      string externalId = physicalPartAppearance.OriginPart.ProcessModelId.ExternalId;
      if (this.m_partExtIdToExistingAppearances.ContainsKey(externalId))
        this.m_partExtIdToExistingAppearances[externalId].Add(physicalPartAppearance);
      else
        this.m_partExtIdToExistingAppearances.Add(externalId, new List<ITxPartAppearance>(1)
        {
          physicalPartAppearance
        });
    }
    this.m_partExtIdToExistingAppearances_IsInitialized = true;
  }

  private void InitExistingSkidAppearances()
  {
    if (this.m_skidToExistingAppearances_IsInitialized)
      return;
    foreach (ITxSkidAppearance allDescendant in (Collection<ITxObject>) TxApplication.ActiveDocument.PhysicalRoot.GetAllDescendants((ITxTypeFilter) new TxTypeFilter(typeof (ITxSkidAppearance))))
    {
      try
      {
        ITxComponent engineeringRepresentation = allDescendant.OriginSkid.EngineeringRepresentation as ITxComponent;
        if (this.m_skidToExistingAppearances.ContainsKey(engineeringRepresentation))
          this.m_skidToExistingAppearances[engineeringRepresentation].Add(allDescendant);
        else
          this.m_skidToExistingAppearances.Add(engineeringRepresentation, new List<ITxSkidAppearance>(1)
          {
            allDescendant
          });
      }
      catch
      {
      }
    }
    this.m_skidToExistingAppearances_IsInitialized = true;
  }

  private ITxLocatableObject GetOrCreatePartAppearance(
    CApObjectSweptVolumePartAppearanceSample partAppearanceSample)
  {
    this.InitExistingPartAppearances();
    string externalId = partAppearanceSample.OriginPart.ProcessModelId.ExternalId;
    if (this.m_partExtIdToExistingAppearances.ContainsKey(externalId))
    {
      List<ITxPartAppearance> existingAppearance = this.m_partExtIdToExistingAppearances[externalId];
      if (existingAppearance.Count > 0)
        return existingAppearance[0] as ITxLocatableObject;
    }
    else
    {
      if (this.m_partExtIdToTempAppearance.ContainsKey(externalId))
        return this.m_partExtIdToTempAppearance[externalId] as ITxLocatableObject;
      if (TxEngineeringDataInternal.GlobalGetPartsMode() == 2)
      {
        ITxPartAppearance partAppearance = (ITxPartAppearance) null;
        try
        {
          partAppearance = ((Collection<ITxObject>) partAppearanceSample.AssignedOperations).Count <= 0 ? TxApplication.ActiveDocument.PhysicalRoot.CreatePartAppearance(partAppearanceSample.OriginPart as ITxPlanningPart, new TxTransformation()) : TxEngineeringDataInternal.GenerateLineSimulationPartAppearance(((Collection<ITxObject>) partAppearanceSample.AssignedOperations)[0] as ITxOperation, partAppearanceSample.OriginPart);
        }
        catch
        {
        }
        if (partAppearance != null)
        {
          this.m_partExtIdToTempAppearance.Add(externalId, partAppearance);
          return partAppearance as ITxLocatableObject;
        }
      }
    }
    return (ITxLocatableObject) null;
  }

  private ITxLocatableObject GetOrCreateSkidAppearance(
    CApObjectSweptVolumeSkidAppearanceSample skidAppearanceSample)
  {
    return this.GetOrCreateSkidAppearance(skidAppearanceSample.OriginSkid);
  }

  private ITxLocatableObject GetOrCreateSkidAppearance(ITxComponent skid)
  {
    if (skid == null)
      return (ITxLocatableObject) null;
    this.InitExistingSkidAppearances();
    if (this.m_skidToExistingAppearances.ContainsKey(skid))
    {
      List<ITxSkidAppearance> existingAppearance = this.m_skidToExistingAppearances[skid];
      if (existingAppearance.Count > 0)
        return existingAppearance[0] as ITxLocatableObject;
    }
    else
    {
      if (this.m_skidToTempAppearance.ContainsKey(skid))
        return this.m_skidToTempAppearance[skid] as ITxLocatableObject;
      ITxSkidAppearance skidAppearance = (ITxSkidAppearance) null;
      try
      {
        skidAppearance = TxEngineeringDataInternal.GenerateSkidAppearance(skid, new TxTransformation());
      }
      catch
      {
      }
      if (skidAppearance != null)
      {
        this.m_skidToTempAppearance.Add(skid, skidAppearance);
        return skidAppearance as ITxLocatableObject;
      }
    }
    return (ITxLocatableObject) null;
  }

  private ITxLocatableObject GetOrCreateSkidAppearanceChild(
    CApObjectSweptVolumeSkidAppearanceChildSample skidAppearanceChildSample)
  {
    ITxLocatableObject skidAppearance = this.GetOrCreateSkidAppearance(skidAppearanceChildSample.OriginSkid);
    if (skidAppearance != null)
    {
      TxObjectList allDescendants = (skidAppearance as ITxObjectCollection).GetAllDescendants((ITxTypeFilter) new TxTypeFilter(typeof (ITxObject)));
      if (skidAppearanceChildSample.ChildIndex >= 0 && skidAppearanceChildSample.ChildIndex < ((Collection<ITxObject>) allDescendants).Count)
        return ((Collection<ITxObject>) allDescendants)[skidAppearanceChildSample.ChildIndex] as ITxLocatableObject;
    }
    return (ITxLocatableObject) null;
  }

  private void SafeDeleteObject(ITxObject obj)
  {
    if (obj == null)
      return;
    try
    {
      if (!obj.IsValid())
        return;
      obj.Delete();
    }
    catch (Exception ex)
    {
    }
  }

  private void beforeCalculateSweptVolume(TxSweptVolumeCalculationData calcData)
  {
    TxObjectSweptVolumeCalculationData[] objectsData = calcData.ObjectsData;
    int length = objectsData != null ? objectsData.GetLength(0) : 0;
    this.m_blankedObjsBeforeCalculate = new TxObjectList<ITxDisplayableObject>(length);
    if (length > 0 && objectsData != null)
    {
      for (int index = 0; index < length; ++index)
      {
        if (objectsData[index].Object is ITxDisplayableObject displayableObject && displayableObject.Visibility == 2)
          ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate).Add(displayableObject);
      }
    }
    int count = ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate).Count;
    if (count <= 0)
      return;
    for (int index = 0; index < count; ++index)
    {
      try
      {
        ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate)[index].Display();
      }
      catch
      {
      }
    }
  }

  private void afterCalculateSweptVolume()
  {
    int count = ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate).Count;
    for (int index = 0; index < count; ++index)
    {
      try
      {
        ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate)[index].Blank();
      }
      catch
      {
      }
    }
    ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate).Clear();
  }
}
